<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

<title>class YARP::ParseResult::Comments - yarp: Ruby Standard Library Documentation</title>


<script src="../../js/navigation.js" defer></script>
<script src="../../js/search.js" defer></script>
<script src="../../js/search_index.js" defer></script>
<script src="../../js/searcher.js" defer></script>
<script src="../../js/darkfish.js" defer></script>

<script src="../../js/jquery-3.2.0.min.js"></script>

<script src="../../js/vue.min.js"></script>
<script src="../../js/js.cookie.min.js"></script>

<link href="../../css/fonts.css" rel="stylesheet">
<link id='rdoccss' href="../../css/rdoc.css" rel="stylesheet">
<link href="../../css/carbon17.css" rel="stylesheet">

<script type="text/javascript">
  var rdoc_rel_prefix = "../../";
  var index_rel_prefix = "../../";
  var darkModeCsseHref = "../../css/rdoc-dm.css"
  var defaultModeCssHref = "../../css/rdoc.css"
  // var cssDarkmode = Cookies.get('darkmode');
  
  if( Cookies.get("darkmode") == "true") {
	$('#rdoccss').attr("href", darkModeCsseHref);
}

//  https://cssdeck.com/blog/simple-jquery-stylesheet-switcher/

document.write('<style type="text/css">body{display:none}</style>');

</script>


</head>
<body id="top" role="document" class="class">
  <!-- this is class.html -->

  <div id='actionbar' >
    <div class='wrapper mdiv'>
      <ul class='grids g0'></ul>
    </div> 
    <!-- VERSION HEADER for 3.3.0.preview2 NOT FOUND -->
  </div> <!-- end action bar -->

  <div class='wrapper hdiv'>

    


    <nav id='vapp' role="navigation">
    <div id="project-navigation">
      <div id="home-section" role="region" title="Quick navigation" class="nav-section">
  <h2><a href="../../index.html" rel="home">Home</a></h2>

  <div id="table-of-contents-navigation"  >
    <a href="../../table_of_contents.html#pages">Pages</a>
    <a href="../../table_of_contents.html#classes">Classes</a>
    <a href="../../table_of_contents.html#methods">Methods</a>
  </div>
</div>

      <div id="search-section" role="search" class="project-section initially-hidden">
  <form action="#" method="get" accept-charset="utf-8">
    <div id="search-field-wrapper">
      <input id="search-field" role="combobox" aria-label="Search"
             aria-autocomplete="list" aria-controls="search-results"
             type="text" name="search" placeholder="Search" spellcheck="false"
             title="Type to search, Up and Down to navigate, Enter to load">
    </div>

    <ul id="search-results" aria-label="Search Results"
        aria-busy="false" aria-expanded="false"
        aria-atomic="false" class="initially-hidden"></ul>
  </form>
</div>

    </div>


    

    <button id='toggleThing' @click="toggleNav()" >Show/hide navigation</button>
    <div :class="isOpen ? 'block' : 'hidden' " id='toggleMe'>
      <div id="class-metadata">
        
        
<div id="parent-class-section" class="nav-section">
  <h3>Parent</h3>

  <p class="link"><a href="../../Object.html">Object</a>
</div>

        
        
        
<!-- Method Quickref -->
<div id="method-list-section" class="nav-section">
  <h3>Methods</h3>

  <ul class="link-list" role="directory">
    <li ><a href="#method-c-new">::new</a>
    <li ><a href="#method-i-attach-21">#attach!</a>
    <li ><a href="#method-i-nearest_targets">#nearest_targets</a>
  </ul>
</div>

      </div>
     </div>
    </nav>


    <div id='extraz'><div class='adzbox-index'  >
      
     </div>         
    </div>

    <main role="main" aria-labelledby="class-YARP::ParseResult::Comments">
    <h1 id="class-YARP::ParseResult::Comments" class="class">
      class YARP::ParseResult::Comments
    </h1>

    <section class="description">
    
<p>When we’ve parsed the source, we have both the syntax tree and the list of comments that we found in the source. This class is responsible for walking the tree and finding the nearest location to attach each comment.</p>

<p>It does this by first finding the nearest locations to each comment. Locations can either come from nodes directly or from location fields on nodes. For example, a ‘ClassNode` has an overall location encompassing the entire class, but it also has a location for the `class` keyword.</p>

<p>Once the nearest locations are found, it determines which one to attach to. If it’s a trailing comment (a comment on the same line as other source code), it will favor attaching to the nearest location that occurs before the comment. Otherwise it will favor attaching to the nearest location that is after the comment.</p>

    </section>

      <section id="5Buntitled-5D" class="documentation-section">



        <section class="attribute-method-details" class="method-section">
        <header>
        <h3>Attributes</h3>
        </header>

          <div id="attribute-i-parse_result" class="method-detail">
            <div class="method-heading attribute-method-heading">
              <span class="method-name">parse_result</span><span
                class="attribute-access-type">[R]</span>
            </div>

            <div class="method-description">
              
              </div>
            </div>
            </section>


                <section id="public-class-5Buntitled-5D-method-details" class="method-section">
                <header>
                <h3>Public Class Methods</h3>
                </header>

                  <div id="method-c-new" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">new</span><span
                                class="method-args">(parse_result)</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              

                              <div class="method-source-code" id="new-source">
            <pre><span class="ruby-comment"># File yarp/parse_result/comments.rb, line 75</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">initialize</span>(<span class="ruby-identifier">parse_result</span>)
  <span class="ruby-ivar">@parse_result</span> = <span class="ruby-identifier">parse_result</span>
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                          </section>

                <section id="public-instance-5Buntitled-5D-method-details" class="method-section">
                <header>
                <h3>Public Instance Methods</h3>
                </header>

                  <div id="method-i-attach-21" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">attach!</span><span
                                class="method-args">()</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              

                              <div class="method-source-code" id="attach-21-source">
            <pre><span class="ruby-comment"># File yarp/parse_result/comments.rb, line 79</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">attach!</span>
  <span class="ruby-identifier">parse_result</span>.<span class="ruby-identifier">comments</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">comment</span><span class="ruby-operator">|</span>
    <span class="ruby-identifier">preceding</span>, <span class="ruby-identifier">enclosing</span>, <span class="ruby-identifier">following</span> = <span class="ruby-identifier">nearest_targets</span>(<span class="ruby-identifier">parse_result</span>.<span class="ruby-identifier">value</span>, <span class="ruby-identifier">comment</span>)
    <span class="ruby-identifier">target</span> =
      <span class="ruby-keyword">if</span> <span class="ruby-identifier">comment</span>.<span class="ruby-identifier">trailing?</span>
        <span class="ruby-identifier">preceding</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">following</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">enclosing</span> <span class="ruby-operator">||</span> <span class="ruby-constant">NodeTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">parse_result</span>.<span class="ruby-identifier">value</span>)
      <span class="ruby-keyword">else</span>
        <span class="ruby-comment"># If a comment exists on its own line, prefer a leading comment.</span>
        <span class="ruby-identifier">following</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">preceding</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">enclosing</span> <span class="ruby-operator">||</span> <span class="ruby-constant">NodeTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">parse_result</span>.<span class="ruby-identifier">value</span>)
      <span class="ruby-keyword">end</span>

    <span class="ruby-identifier">target</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">comment</span>
  <span class="ruby-keyword">end</span>
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                          </section>

                <section id="private-instance-5Buntitled-5D-method-details" class="method-section">
                <header>
                <h3>Private Instance Methods</h3>
                </header>

                  <div id="method-i-nearest_targets" class="method-detail ">
                            <div class="method-heading">
                              <span class="method-name">nearest_targets</span><span
                                class="method-args">(node, comment)</span>
                              <span class="method-click-advice">click to toggle source</span>
                            </div>

                            <div class="method-description">
                              <p>Responsible for finding the nearest targets to the given comment within the context of the given encapsulating node.</p>

                              <div class="method-source-code" id="nearest_targets-source">
            <pre><span class="ruby-comment"># File yarp/parse_result/comments.rb, line 98</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">nearest_targets</span>(<span class="ruby-identifier">node</span>, <span class="ruby-identifier">comment</span>)
  <span class="ruby-identifier">comment_start</span> = <span class="ruby-identifier">comment</span>.<span class="ruby-identifier">location</span>.<span class="ruby-identifier">start_offset</span>
  <span class="ruby-identifier">comment_end</span> = <span class="ruby-identifier">comment</span>.<span class="ruby-identifier">location</span>.<span class="ruby-identifier">end_offset</span>

  <span class="ruby-identifier">targets</span> = []
  <span class="ruby-identifier">node</span>.<span class="ruby-identifier">comment_targets</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">value</span><span class="ruby-operator">|</span>
    <span class="ruby-keyword">case</span> <span class="ruby-identifier">value</span>
    <span class="ruby-keyword">when</span> <span class="ruby-constant">StatementsNode</span>
      <span class="ruby-identifier">targets</span>.<span class="ruby-identifier">concat</span>(<span class="ruby-identifier">value</span>.<span class="ruby-identifier">body</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">node</span><span class="ruby-operator">|</span> <span class="ruby-constant">NodeTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">node</span>) })
    <span class="ruby-keyword">when</span> <span class="ruby-constant">Node</span>
      <span class="ruby-identifier">targets</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-constant">NodeTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">value</span>)
    <span class="ruby-keyword">when</span> <span class="ruby-constant">Location</span>
      <span class="ruby-identifier">targets</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-constant">LocationTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">value</span>)
    <span class="ruby-keyword">end</span>
  <span class="ruby-keyword">end</span>

  <span class="ruby-identifier">targets</span>.<span class="ruby-identifier">sort_by!</span>(<span class="ruby-operator">&amp;</span><span class="ruby-value">:start_offset</span>)
  <span class="ruby-identifier">preceding</span> = <span class="ruby-keyword">nil</span>
  <span class="ruby-identifier">following</span> = <span class="ruby-keyword">nil</span>

  <span class="ruby-identifier">left</span> = <span class="ruby-value">0</span>
  <span class="ruby-identifier">right</span> = <span class="ruby-identifier">targets</span>.<span class="ruby-identifier">length</span>

  <span class="ruby-comment"># This is a custom binary search that finds the nearest nodes to the</span>
  <span class="ruby-comment"># given comment. When it finds a node that completely encapsulates the</span>
  <span class="ruby-comment"># comment, it recurses downward into the tree.</span>
  <span class="ruby-keyword">while</span> <span class="ruby-identifier">left</span> <span class="ruby-operator">&lt;</span> <span class="ruby-identifier">right</span>
    <span class="ruby-identifier">middle</span> = (<span class="ruby-identifier">left</span> <span class="ruby-operator">+</span> <span class="ruby-identifier">right</span>) <span class="ruby-operator">/</span> <span class="ruby-value">2</span>
    <span class="ruby-identifier">target</span> = <span class="ruby-identifier">targets</span>[<span class="ruby-identifier">middle</span>]

    <span class="ruby-identifier">target_start</span> = <span class="ruby-identifier">target</span>.<span class="ruby-identifier">start_offset</span>
    <span class="ruby-identifier">target_end</span> = <span class="ruby-identifier">target</span>.<span class="ruby-identifier">end_offset</span>

    <span class="ruby-keyword">if</span> <span class="ruby-identifier">target</span>.<span class="ruby-identifier">encloses?</span>(<span class="ruby-identifier">comment</span>)
      <span class="ruby-comment"># The comment is completely contained by this target. Abandon the</span>
      <span class="ruby-comment"># binary search at this level.</span>
      <span class="ruby-keyword">return</span> <span class="ruby-identifier">nearest_targets</span>(<span class="ruby-identifier">target</span>.<span class="ruby-identifier">node</span>, <span class="ruby-identifier">comment</span>)
    <span class="ruby-keyword">end</span>

    <span class="ruby-keyword">if</span> <span class="ruby-identifier">target_end</span> <span class="ruby-operator">&lt;=</span> <span class="ruby-identifier">comment_start</span>
      <span class="ruby-comment"># This target falls completely before the comment. Because we will</span>
      <span class="ruby-comment"># never consider this target or any targets before it again, this</span>
      <span class="ruby-comment"># target must be the closest preceding target we have encountered so</span>
      <span class="ruby-comment"># far.</span>
      <span class="ruby-identifier">preceding</span> = <span class="ruby-identifier">target</span>
      <span class="ruby-identifier">left</span> = <span class="ruby-identifier">middle</span> <span class="ruby-operator">+</span> <span class="ruby-value">1</span>
      <span class="ruby-keyword">next</span>
    <span class="ruby-keyword">end</span>

    <span class="ruby-keyword">if</span> <span class="ruby-identifier">comment_end</span> <span class="ruby-operator">&lt;=</span> <span class="ruby-identifier">target_start</span>
      <span class="ruby-comment"># This target falls completely after the comment. Because we will</span>
      <span class="ruby-comment"># never consider this target or any targets after it again, this</span>
      <span class="ruby-comment"># target must be the closest following target we have encountered so</span>
      <span class="ruby-comment"># far.</span>
      <span class="ruby-identifier">following</span> = <span class="ruby-identifier">target</span>
      <span class="ruby-identifier">right</span> = <span class="ruby-identifier">middle</span>
      <span class="ruby-keyword">next</span>
    <span class="ruby-keyword">end</span>

    <span class="ruby-comment"># This should only happen if there is a bug in this parser.</span>
    <span class="ruby-identifier">raise</span> <span class="ruby-string">&quot;Comment location overlaps with a target location&quot;</span>
  <span class="ruby-keyword">end</span>

  [<span class="ruby-identifier">preceding</span>, <span class="ruby-constant">NodeTarget</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">node</span>), <span class="ruby-identifier">following</span>]
<span class="ruby-keyword">end</span></pre>
                              </div>
                            </div>


                          </div>

                          </section>

              </section>
              </main>



            </div>  <!--  class='wrapper hdiv' -->


<footer id="validator-badges" role="contentinfo">
<p><a href="https://validator.w3.org/check/referer">Validate</a></p>
<p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> 6.4.0.</p>
<p>Based on <a href="https://github.com/ged/darkfish/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.</p>

  
    <p><p><a href="https://ruby-doc.org">Ruby-doc.org</a> is provided by <a href="https://jamesbritt.com">James Britt</a> and <a href="https://neurogami.com">Neurogami</a>. </p><p><a href="https://jamesbritt.bandcamp.com/">Hack your world.  Feed your head.  Live curious</a>.</p>
</p>
  
  </footer>

<script type="text/javascript">


  let ads  = $("#carbonads-container").children().detach();


  function swapMode() {
    var cookieName = 'darkmode';
    var cssDarkmode = Cookies.get(cookieName);
    console.log("***** swapMode! " + cssDarkmode + " *****");


    if (cssDarkmode == "true") {
      console.log("We have dark mode, set the css to light ...");
      $('#rdoccss').attr("href", defaultModeCssHref);
      $('#cssSelect').text("Dark mode");
      cssDarkmode = "false";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    } else {
      console.log("We not have dark mode, set the css to dark ...");
      $('#rdoccss').attr("href", darkModeCsseHref);
      $('#cssSelect').text("Light mode");
      cssDarkmode = "true";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    }

    console.log("  --------------- ");
  }


const vueCssApp = new Vue({
el: '#menubar',
data: {
isDark: false
},
methods: {
toggleClass: function(event){
this.isDark = !this.isDark;
}
}
})

const vueApp = new Vue({
el: '#vapp',
data: { 
isOpen: true
},

mounted() {
this.handleResize();
this.manage_mob_classes();
window.addEventListener('resize', this.handleResize)
//this.isOpen !=  (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},
destroyed() {
window.removeEventListener('resize', this.handleResize)
},
created() {
//manage_mob_classes();
},

methods : {
isMobile() {
  return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},

  handleResize() {
    if (!this.isMobile()) {
      this.isOpen = window.innerWidth > 800;
    }
  },

  manage_mob_classes() {
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
      $("nav").addClass("mob_nav");
      $("main").addClass("mob_main");
      $("#extraz").addClass("mob_extraz");
      $("#carbonads-container").addClass("mob_carbonads-container");
      this.isOpen  = false;
    } else {
      $("nav").removeClass("mob_nav") 
        $("main").removeClass("mob_main");
      $("#extraz").removeClass("mob_extraz");
      $("#carbonads-container").removeClass("mob_carbonads-container");
      this.isOpen  = true;
    }
  },

  toggleNav() {
    this.isOpen =! this.isOpen ;
    // alert("Toggle nav!");
    console.log("toggleNav() click: " + this.isOpen );
  }
}
})

$("#carbonads-container").append(ads);


$(function() {

    var darkmode = Cookies.get("darkmode");
    console.log("Document ready: " + darkmode);

    if ( darkmode  == "true" ) {
      $('#cssSelect').text("Light mode");
    } else {
      $('#cssSelect').text("Dark mode");
     }

    $('body').css('display','block');
    });

</script>

    
  </body> 
</html>

